package RPC;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import BasicDataType.IPP;
import cs5300.SessionManager;
import cs5300.SessionTable;
import cs5300.indexDisplayWrapper;
import cs5300.sessionState;

public class RPCserver implements Runnable {

	public static IPP serverAddress;
	int port;
	boolean stop = false;

	public RPCserver(int port) {
		this.port = port;
	}

	public void stop() {
		stop = true;
	}

	@Override
	public void run() {
		try {
			DatagramSocket rpcSocket = new DatagramSocket(port);
			if (serverAddress == null) {
				serverAddress = new IPP();
				serverAddress.IPaddress = InetAddress.getLocalHost();
				serverAddress.Port = rpcSocket.getLocalPort();
			}
			// init desList.

			while (!stop) {
				byte[] inBuf = new byte[1024];
				DatagramPacket recvPkt = new DatagramPacket(inBuf, inBuf.length);
				rpcSocket.receive(recvPkt);
				InetAddress returnAddr = recvPkt.getAddress();
				int returnPort = recvPkt.getPort();
				// here inBuf contains the callID and operationCode
				String request = new String(recvPkt.getData());
				RequestMessage reqM = new RequestMessage(request);
				indexDisplayWrapper.evict = reqM.opeID;
				String opeID = reqM.opeID;
				byte[] sendData = new byte[1024];
				// DatagramPacket dgp = new DatagramPacket(sendData,
				// sendData.length, returnAddr, returnPort);
				SessionTable st = SessionTable.getInstance();
				if (opeID.equals(RPCConstants.SESSIONREAD)) {
					SessionManager sManager = SessionManager.getInstance();
					if (sManager.validCookie(reqM.ss.cookie)) {
						sessionState localSess = st.getState(reqM.ss.cookie.sessionID);
						ResponseMessage resM = new ResponseMessage();
						resM.callID = reqM.callID;
						resM.opeID = reqM.opeID;
						resM.result = localSess.getString();
						sendData = resM.getString().getBytes();
						DatagramPacket dgp = new DatagramPacket(sendData, sendData.length, returnAddr, returnPort);
						rpcSocket.send(dgp);
					}

					// outBuf = resM.getString().getBytes();
				} else if (opeID.equals(RPCConstants.SESSIONWRITE)) {
					sessionState ss = reqM.ss;
					boolean sendAck = st.insertSession(ss);
					if (sendAck) {
						ResponseMessage resM = new ResponseMessage();
						resM.callID = reqM.callID;
						resM.opeID = reqM.opeID;
						resM.result = RPCConstants.SUCCESS;
						sendData = resM.getString().getBytes();
						DatagramPacket dgp = new DatagramPacket(sendData, sendData.length, returnAddr, returnPort);
						rpcSocket.send(dgp);
					}

				} else if (opeID.equals(RPCConstants.SESSIONDELETE)) {
					boolean sendAck = st.removeState(reqM.ss.cookie.sessionID);
					if (sendAck) {
						ResponseMessage resM = new ResponseMessage();
						resM.callID = reqM.callID;
						resM.opeID = reqM.opeID;
						resM.result = RPCConstants.SUCCESS;
						sendData = resM.getString().getBytes();
						DatagramPacket dgp = new DatagramPacket(sendData, sendData.length, returnAddr, returnPort);
						rpcSocket.send(dgp);
					}
				} else if (opeID.equals(RPCConstants.SESSIONPING)) {
					System.out.println("Session Ping received");
					// TODO: receive Ping request, response a signal message
					ResponseMessage resM = new ResponseMessage();
					resM.callID = reqM.callID;
					resM.opeID = reqM.opeID;
					resM.result = "PingReceived";
					sendData = resM.getString().getBytes();
					DatagramPacket dgp = new DatagramPacket(sendData, sendData.length, returnAddr, returnPort);
					rpcSocket.send(dgp);
				}

			}

		} catch (IOException e) {
			// TODO: handle exception
		} catch (Exception e) {
			System.out.println(e.getLocalizedMessage());
		}

	}
}
